#pragma once

#include <iostream>
#include <string>
#include <string.h>
#include <ctime>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <cassert>

#define NOTICE 1
#define WARNING 2
#define DEBUG 3
#define FATAL 4

#define LOG(LEVEL, MESSAGE) log(#LEVEL, MESSAGE, __FILE__, __LINE__)
#define LOGERR(MESSAGE) logerr(MESSAGE, __FILE__, __LINE__)

// 默认日志文件
#define LOG_PATH "./log/log.txt"

class Redirect
{
public:
    Redirect(const char *DebugPath = LOG_PATH, const char *ErrorPath = LOG_PATH)
    {
        umask(0);
        if (strcmp(DebugPath, ErrorPath) == 0)
        {
            DebugFd = ErrorFd = open(DebugPath, O_WRONLY | O_CREAT | O_APPEND, 0666);
            assert(DebugFd != -1);
        }
        else
        {
            DebugFd = open(DebugPath, O_WRONLY | O_CREAT | O_APPEND, 0666);
            ErrorFd = open(ErrorPath, O_WRONLY | O_CREAT | O_APPEND, 0666);
            assert(DebugFd != -1 && ErrorFd != -1);
        }
        // 重定向
        dup2(DebugFd, 1);
        dup2(ErrorFd, 2);
    }

    ~Redirect()
    {
        fsync(DebugFd);
        fsync(ErrorFd);
        close(DebugFd);
        close(ErrorFd);
    }

private:
    int DebugFd;
    int ErrorFd;
};

void log(std::string level, std::string message, std::string file, int line)
{
    std::cout << "[" << level << "]"
              << "[" << time(nullptr) << "]"
              << "[" << message << "]"
              << "[" << file << " : " << line << "]" << std::endl;
    fflush(stdout); // 将C缓冲区中的数据刷新到OS
    fsync(fileno(stdout));// 将OS中的数据写入硬盘
}

void logerr(std::string message, std::string file, int line)
{
    std::cerr << "[FATAL]"
              << "[" << time(nullptr) << "]"
              << "[" << message << "]"
              << "[" << file << " : " << line << "]" << std::endl;
    fflush(stderr); // 将C缓冲区中的数据刷新到OS
    fsync(fileno(stderr));// 将OS中的数据写入硬盘
}